package com.asyf.demo.config;

import com.asyf.demo.annotation.MyDS;
import com.asyf.demo.exception.ExceptionEnum;
import com.asyf.demo.exception.GlobalException;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * <p>
 * 数据源选择器切面
 * </p>
 *
 * @author starsray
 * @since 2021-11-10
 */
@Aspect
@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class MyDsInterceptor implements HandlerInterceptor {

    @Pointcut("@annotation(com.asyf.demo.annotation.MyDS)")
    public void datasourcePointcut() {
    }

    /**
     * 前置操作，拦截具体请求，获取header里的数据源id，设置线程变量里，用于后续切换数据源
     */
    @Before("datasourcePointcut()")
    public void doBefore(JoinPoint joinPoint) {


        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        MyDS annotation = method.getAnnotation(MyDS.class);//注解

        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        //这里有可以通过其他方式判断应该使用哪个数据源
        String header = request.getHeader("tenantName");
        if (StringUtils.isNotBlank(header)) {
            DynamicDataSourceContextHolder.push(header);
        } else {
            throw new GlobalException(ExceptionEnum.NOT_TENANT);
        }
    }

    /**
     * 后置操作，设置回默认的数据源id
     */
    @AfterReturning("datasourcePointcut()")
    public void doAfter() {
        DynamicDataSourceContextHolder.push("master");
    }

}
